package com.dl.mall.service.admin.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dl.mall.entity.Page;
import com.dl.mall.entity.Product;
import com.dl.mall.entity.ProductSpecs;
import com.dl.mall.mapper.ProductMapper;
import com.dl.mall.service.admin.ProductService_Admin;
import com.dl.mall.utils.AliyunOssUtils;
import com.dl.mall.utils.PageUtils;
import com.dl.mall.utils.UUIDUtils;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author DL
 * @create 2022-04-11 13:21
 */
@Service
@Transactional
@Slf4j
public class ProductServiceImpl_Admin implements ProductService_Admin {

    @Resource
    private ProductMapper productMapper;

    /* ======================================admin=================================== */

    /**
     * 解析spu信息
     * @param spuJson spuJson
     * @return 解析后的map
     */
    public Map<String, Object> parseSpu(String spuJson){
        JSONObject jsonObject = JSON.parseObject(spuJson);
        // 存放分区和品牌id，是一个list，所以需要再次提取信息
        JSONArray categoryAndBrand = jsonObject.getJSONArray("categoryAndBrand");

        HashMap<String, Object> spuMap = new HashMap<>();
        spuMap.put("productId", jsonObject.getString("productId"));// 产品id
        spuMap.put("categoryId", categoryAndBrand.getIntValue(0));// 分区id
        spuMap.put("brandId", categoryAndBrand.getIntValue(1));// 品牌id
        spuMap.put("name", jsonObject.getString("name"));// 产品名称
        spuMap.put("title", jsonObject.getString("title"));// 产品标题
        spuMap.put("describe", jsonObject.getString("describe"));// 产品描述
        spuMap.put("detail", jsonObject.getString("detail"));// 产品详情
        spuMap.put("dbAttributeList", jsonObject.getString("dbAttributeList"));// 规格信息
        spuMap.put("price", jsonObject.getBigDecimal("price"));// 最低价格
        spuMap.put("state", jsonObject.getIntValue("state"));// 状态
        return spuMap;
    }

    /**
     * 解析sku信息
     * @param skuJson skuJson
     * @param specsPrefix 规格图片的前缀
     * @return map集合，解析后的sku信息 和 规格图片名称集合
     */
    public List<Map<String, Object>> parseSku(MultipartFile[] specsImgFile, String skuJson, String specsPrefix){
        JSONArray jsonArray = JSON.parseArray(skuJson);// 解析skuJson
        //System.out.println("jsonArray = " + jsonArray);

        List<Map<String, Object>> skuList = new ArrayList<>();// 存放转换后的skuList

        int i = 0;
        for (Object sku : jsonArray) {
            HashMap<String, Object> skuMap = new HashMap<>();// 存放skuJson->skuMap的信息
            System.out.println("forEach sku = " + sku);
            JSONObject skuObject = (JSONObject) sku;

            //String specsId = skuObject.getString("specsId");// 规格id，用来作为图片名称和图片存储路径

            String productId = skuObject.getString("productId");
            skuMap.put("productId", productId);
            skuMap.put("specsId", productId + "-" + UUIDUtils.getUUID5());
            skuMap.put("productSpecs", skuObject.getString("productSpecs"));
            /*skuMap.put("specsImg", specsPrefix + specsId);*/
            skuMap.put("price", skuObject.getBigDecimal("price"));
            skuMap.put("specsStock", skuObject.getIntValue("specsStock"));
            skuMap.put("state", skuObject.getIntValue("state"));
            System.out.println("skuObject.getString(\"productSpecs\") = " + skuObject.getString("productSpecs"));
            System.out.println("skuMap.get(\"productSpecs\") = " + skuMap.get("productSpecs"));
            try {
                String specsImgString = AliyunOssUtils.specsImgUpload(specsPrefix, String.valueOf(skuMap.get("specsId")), specsImgFile[i]);
                //String specsImg = FileUtils.uploadSpecsImg(specsImgFile[i], specsPrefix, specsId);
                //System.out.println("specsImgString = " + specsImgString);
                skuMap.put("specsImg", specsImgString);
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
            skuList.add(skuMap);// 添加skuJson->skuMap的信息
            i++;
        }
        return skuList;
    }

    /**
     * 根据 id 查询产品
     * @param productId 产品id
     * @return 是否存在
     */
    @Override
    public boolean isExistProduct(String productId) {
        Product product = productMapper.queryProductById(productId);
        return product != null;
    }

    @Override
    public boolean modifySpecsStock(String specsId, Integer specsStock) {
        return productMapper.updateSpecsStock(specsId, specsStock) != 0;
    }

    @Override
    public boolean modifySpecsState(String specsId, Integer state) {
        return productMapper.updateSpecsState(specsId, state) != 0;
    }

    @Override
    public boolean modifyProductState(String productId, Integer state) {
        return productMapper.updateProductState(productId, state) != 0;
    }

    /**
     * 增加产品
     * @param spuJson spu信息
     * @param skuJson sku信息（多个）
     * @param mainImg 主图
     * @param subImg 副图（多个）
     * @param specsImg 规格图（多个）
     * @return 是否成功
     */
    @Override
    public boolean addProduct(String spuJson,
                              String skuJson,
                              MultipartFile mainImg,
                              MultipartFile[] subImg,
                              MultipartFile[] specsImg) {

        Map<String, Object> spuMap = parseSpu(spuJson);
        System.out.println("spuMap = " + spuMap);

        int categoryId = (int) spuMap.get("categoryId");// 分区id
        int brandId = (int) spuMap.get("brandId");// 品牌id
        String productId = (String) spuMap.get("productId");// 产品id

        String mainImgPrefix = "product-mainImg/" +  categoryId + "/" + brandId + "/";
        String subImgPrefix = "product-subImg/" +  categoryId + "/" + brandId + "/" + productId + "/";
        String specsImgPrefix = "product-specsImg/" +  categoryId + "/" + brandId + "/" + productId + "/";

        try {
            String mainImgString = AliyunOssUtils.uploadFile(mainImgPrefix, productId, mainImg);
            String subImgString = AliyunOssUtils.subImgUpload(subImgPrefix, subImg);

            //System.out.println("mainImgName = " + mainImgString);
            //System.out.println("subImgName = " + subImgString);
            spuMap.put("mainImg", mainImgString);
            spuMap.put("subImg", subImgString);

            List<Map<String, Object>> skuList = parseSku(specsImg, skuJson, specsImgPrefix);

            if (mainImgString != null && subImgString != null){
                int i = productMapper.insertProductSpu(spuMap);
                int i1 = productMapper.insertProductSku(skuList);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * 根据 产品id 获得产品spu信息
     * @param productId 产品id
     * @return 产品spu
     */
    @Override
    public Product getSPU(String productId) {
        return productMapper.queryProductById(productId);
    }

    /**
     * 根据 产品id 获得产品sku信息
     * @param productId 产品id
     * @return 产品sku
     */
    @Override
    public List<ProductSpecs> getSKU(String productId) {
        return productMapper.queryProductSpecsById(productId);
    }


    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    @Override
    public boolean preheat() {
        List<ProductSpecs> productSpecsList = productMapper.queryProductSpecsList();
        RedisSerializer<String> serializer = redisTemplate.getStringSerializer();

        HashMap<byte[], byte[]> map = new HashMap<>();
        productSpecsList.forEach(productSpecs->{
            map.put(productSpecs.getSpecsId().getBytes(), serializer.serialize(productSpecs.getSpecsStock().toString()));
        });
        List<Object> list = redisTemplate.executePipelined(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                connection.hMSet("productSpecs".getBytes(), map);
                return null;
            }
        }, serializer);

        return true;
    }

    /**
     * 根据 条件 查询产品列表
     * @param jsonObject 条件
     * @return 产品分页
     */
    @Override
    public Page<Product> getProductListByCondition(JSONObject jsonObject) {
        JSONObject condition = jsonObject.getJSONObject("condition"); // 总条件
        JSONObject category = condition.getJSONObject("category"); // 分区

        boolean phone = category.getBooleanValue("phone");
        boolean computer = category.getBooleanValue("computer");
        boolean camera = category.getBooleanValue("camera");
        boolean accessory = category.getBooleanValue("accessory");

        ArrayList<Integer> categoryIdList = new ArrayList<>();// 分区id集合
        if (phone) categoryIdList.add(1);
        if (computer) categoryIdList.add(2);
        if (camera) categoryIdList.add(3);
        if (accessory) categoryIdList.add(4);

        Map<String, Object> map = new HashMap<>();
        map.put("categoryIdList", categoryIdList);
        map.put("name", condition.getString("name"));
        map.put("state", condition.getInteger("state"));

        Integer currentPage = condition.getInteger("currentPage");
        PageHelper.startPage(currentPage, 10);
        System.out.println("map = " + map);
        List<Product> list = productMapper.queryProductListCondition(map);
        return (Page<Product>) PageUtils.getPage(list);
    }
}
